home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 April: Mac OS SDK / Dev.CD Apr 00 SDK1.toast / Development Kits / Mac OS / Installer SDK 1.2.3 / Upgrader 1.2.3 & Engines / Upgrader 1.2.3 / Plug-in Examples / Common Files / MWCPlusExtensions / NMWException.cp < prev    next >
Encoding:
Text File  |  1997-04-07  |  11.2 KB  |  332 lines  |  [TEXT/CWIE]

  1. /************************************************************************/
  2. /*    Project...:    Standard C++ Library                                    */
  3. /*    Name......:    MWException.cp                                            */
  4. /*    Purpose...:    portable exception handling                                */
  5. /*  Copyright.: ©Copyright 1993-95 by metrowerks inc                    */
  6. /************************************************************************/
  7.  
  8. #ifdef __MC68K__
  9. #pragma far_data off
  10. #endif
  11.  
  12. #define __NOSTRING__    //    do not include <string>
  13.  
  14. #include <Types.h>
  15. #include <stdlib.h>
  16. #include <CPlusLib.h>
  17. #include <exception.h>
  18. #include "NMWException.h"
  19.  
  20. static void dthandler()        { abort(); };            //    default terminate handler function
  21. static terminate_handler    thandler = dthandler;    //    pointer to terminate handler function
  22. static void duhandler()        { terminate(); };        //    default unexpected handler function
  23. static unexpected_handler    uhandler = duhandler;    //    pointer to unexpected handler function
  24.  
  25. /************************************************************************/
  26. /*    Purpose..:     Set a terminate handler function                        */
  27. /*    Input....:    pointer to terminate handler function                    */
  28. /*    Return...:    ---                                                        */
  29. /************************************************************************/
  30. extern terminate_handler set_terminate(terminate_handler handler)
  31. {
  32.     terminate_handler old=thandler; thandler=handler; return old;
  33. }
  34.  
  35. /************************************************************************/
  36. /*    Purpose..:     Terminate exception handling                            */
  37. /*    Input....:    ---                                                        */
  38. /*    Return...:    --- (shall not return to caller)                        */
  39. /************************************************************************/
  40. extern void terminate()
  41. {
  42.     thandler();
  43. }
  44.  
  45. /************************************************************************/
  46. /*    Purpose..:     Set an unexpected handler function                        */
  47. /*    Input....:    pointer to unexpected handler function                    */
  48. /*    Return...:    ---                                                        */
  49. /************************************************************************/
  50. extern unexpected_handler set_unexpected(unexpected_handler handler)
  51. {
  52.     unexpected_handler old=uhandler; uhandler=handler; return old;
  53. }
  54.  
  55. /************************************************************************/
  56. /*    Purpose..:     Handle unexpected exception                                */
  57. /*    Input....:    ---                                                        */
  58. /*    Return...:    --- (shall not return to caller)                        */
  59. /************************************************************************/
  60. extern void unexpected()
  61. {
  62.     uhandler();
  63. }
  64.  
  65. /************************************************************************/
  66. /*    Purpose..:     Register a global object for later destruction            */
  67. /*    Input....:    pointer to global object                                */
  68. /*    Input....:    pointer to destructor function                            */
  69. /*    Input....:    pointer to global registration structure                */
  70. /*    Return...:    pointer to global object (pass thru)                    */
  71. /************************************************************************/
  72. #if !defined(__POWERPC__) && !defined(__CFM68K__)        //    only needed for classic 68K ...
  73.  
  74. extern void *__register_global_object(void *object,void *destructor,void *regmem)
  75. {
  76.     ((DestructorChain *)regmem)->next=__global_destructor_chain;
  77.     ((DestructorChain *)regmem)->destructor=destructor;
  78.     ((DestructorChain *)regmem)->object=object;
  79.     __global_destructor_chain=(DestructorChain *)regmem;
  80.  
  81.     return object;
  82. }
  83.  
  84. #endif
  85.  
  86. /************************************************************************/
  87. /* Purpose..: Compare a throw and a catch type                            */
  88. /* Input....: pointer to throw type                                        */
  89. /* Input....: pointer to catch type (0L: catch(...)                        */
  90. /* Return...: true: can catch; false: cannot catch                        */
  91. /************************************************************************/
  92. extern char __throw_catch_compare(const char *throwtype,const char *catchtype,long *offset_result)
  93. {
  94.     const char    *cptr1,*cptr2;
  95.  
  96.     *offset_result=0;
  97.     if((cptr2=catchtype)==0) return true;        //    catch(...)
  98.     cptr1=throwtype;
  99.     switch(*cptr1)
  100.     {
  101.     case '*':
  102.     case '!':
  103.         if(*cptr1++==*cptr2++) for(;;)
  104.         {    //    class name compare loop
  105.             if(*cptr1==*cptr2++)
  106.             {
  107.                 if(*cptr1++=='!')
  108.                 {    //    class match found / get offset
  109.                     long offset;
  110.  
  111.                     for(offset=0; *cptr1!='!';) offset=offset*10+*cptr1++-'0';
  112.                     *offset_result=offset; return true;
  113.                 }
  114.             }
  115.             else
  116.             {
  117.                 while(*cptr1++!='!') ;    //    skip class name
  118.                 while(*cptr1++!='!') ;    //    skip offset
  119.                 if(*cptr1==0) break;    //    break if no more class names
  120.                 cptr2=catchtype+1;        //    retry with next class name
  121.             }
  122.         }
  123.         break;
  124.  
  125.     default:
  126.         for(; *cptr1==*cptr2; cptr1++,cptr2++) if(*cptr1==0) return true;
  127.         break;
  128.     }
  129.     return false;
  130. }
  131.  
  132. #if defined(__MC68K__)    
  133.  
  134. /************************************************************************/
  135. /*    Purpose..:     Initialize a new allocated array of objects                */
  136. /*    Input....:    pointer to allocated memory (+8 bytes) (0L: error)        */
  137. /*    Input....:    pointer to default constructor function    (or 0L)            */
  138. /*    Input....:    pointer to destructor function (or 0L)                    */
  139. /*    Input....:    size of one array element                                */
  140. /*    Input....:    number of array elements                                */
  141. /*    Return...:    pointer to first object in array                        */
  142. /************************************************************************/
  143. extern void *__construct_new_array(void *block,ConstructorDestructor ctor,ConstructorDestructor dtor_arg,size_t size,size_t n)
  144. {
  145.     char    *ptr;
  146.  
  147.     if((ptr=(char *)block)!=0L)
  148.     {
  149.         //    store number of allocated objects and size of one object at the beginnig of the allocated block
  150.         *(size_t *)ptr=size;
  151.         *(size_t *)(ptr+sizeof(size_t))=n;
  152.         ptr+=sizeof(size_t)*2;
  153.  
  154.         if(ctor)
  155.         {    //    call constructor to initialize array
  156.             volatile ConstructorDestructor    dtor=dtor_arg;    //    force reference to dtor
  157.             char                            *p;
  158.             size_t                            i;
  159.  
  160.             #pragma exception_arrayinit
  161.             //    this #pragma adds partial array construction exception action (ptr,dtor,size,i)
  162.  
  163.             for(i=0,p=ptr; i<n; i++,p+=size)
  164.             {
  165.                 CTORCALL_COMPLETE(ctor,p);
  166.             }
  167.         }
  168.     }
  169.     return ptr;    //    return pointer to first object;
  170. }
  171.  
  172. /************************************************************************/
  173. /*    Purpose..:     Construct an array of objects                            */
  174. /*    Input....:    pointer to array memory                                    */
  175. /*    Input....:    pointer to default constructor function                    */
  176. /*    Input....:    pointer to destructor function (or 0L)                    */
  177. /*    Input....:    size of one array element                                */
  178. /*    Input....:    number of array elements                                */
  179. /*    Return...:    ---                                                        */
  180. /************************************************************************/
  181. extern void __construct_array(void *ptr,ConstructorDestructor ctor,ConstructorDestructor dtor_arg,size_t size,size_t n)
  182. {
  183.     volatile ConstructorDestructor    dtor=dtor_arg;    //    force reference to dtor
  184.     char                            *p;
  185.     size_t                            i;
  186.  
  187.     #pragma exception_arrayinit
  188.     //    this #pragma adds partial array construction exception action (ptr,dtor,size,i)
  189.  
  190.     for(i=0,p=(char *)ptr; i<n; i++,p+=size)
  191.     {
  192.         CTORCALL_COMPLETE(ctor,p);
  193.     }
  194. }
  195.  
  196. #else
  197.  
  198. //    class __partial_array_destructor
  199. //
  200. //        This class is used to guarantee correct destruction of partially
  201. //        constructed arrays if an exception is thrown from an array-element constructor.
  202. //        We use the members of this class to keep track of the partially-constructed
  203. //        state of the array. If the destructor for this class is called and the
  204. //        array was not fully-constructed, we must have thrown an exception, so we
  205. //        destroy each fully-constructed element of the array in reverse order.
  206.  
  207. class __partial_array_destructor {
  208. private:
  209.     void*                    p;        //    pointer to start of array being constructed
  210.     size_t                    size;    //    size of each array element
  211.     size_t                    n;        //    # of elements being constructed
  212.     ConstructorDestructor    dtor;    //    pointer to destructor for elements or 0
  213. public:
  214.     size_t                    i;        //    current element being constructed
  215.     
  216.     __partial_array_destructor(void* array, size_t elementsize, size_t nelements, ConstructorDestructor destructor)
  217.     {
  218.         p=array; size=elementsize; n=nelements; dtor=destructor; i=n;
  219.     }
  220.         
  221.     ~__partial_array_destructor()
  222.     {
  223.         char *ptr;
  224.         
  225.         if(i<n && dtor)
  226.         {
  227.             for(ptr=(char *)p+size*i; i>0; i--)
  228.             {
  229.                 ptr-=size;
  230.                 DTORCALL_COMPLETE(dtor,ptr);
  231.             }
  232.         }
  233.     }
  234. };
  235.  
  236. /************************************************************************/
  237. /*    Purpose..:     Initialize a new allocated array of objects                */
  238. /*    Input....:    pointer to allocated memory (+8 bytes) (0L: error)        */
  239. /*    Input....:    pointer to default constructor function    (or 0L)            */
  240. /*    Input....:    pointer to destructor function (or 0L)                    */
  241. /*    Input....:    size of one array element                                */
  242. /*    Input....:    number of array elements                                */
  243. /*    Return...:    pointer to first object in array                        */
  244. /************************************************************************/
  245. extern void *__construct_new_array(void *block,ConstructorDestructor ctor,ConstructorDestructor dtor,size_t size,size_t n)
  246. {
  247.     char    *ptr;
  248.  
  249.     if((ptr=(char *)block)!=0L)
  250.     {
  251.         //    store number of allocated objects and size of one object at the beginnig of the allocated block
  252.         *(size_t *)ptr=size;
  253.         *(size_t *)(ptr+sizeof(size_t))=n;
  254.         ptr+=sizeof(size_t)*2;
  255.  
  256.         if(ctor)
  257.         {    //    call constructor to initialize array
  258.             __partial_array_destructor pad(ptr,size,n,dtor);
  259.             char    *p;
  260.  
  261.             for(pad.i=0,p=(char *)ptr; pad.i<n; pad.i++,p+=size) CTORCALL_COMPLETE(ctor,p);
  262.         }
  263.     }
  264.     return ptr;    //    return pointer to first object;
  265. }
  266.  
  267. /************************************************************************/
  268. /*    Purpose..:     Construct an array of objects                            */
  269. /*    Input....:    pointer to array memory                                    */
  270. /*    Input....:    pointer to default constructor function                    */
  271. /*    Input....:    pointer to destructor function (or 0L)                    */
  272. /*    Input....:    size of one array element                                */
  273. /*    Input....:    number of array elements                                */
  274. /*    Return...:    ---                                                        */
  275. /************************************************************************/
  276. extern void __construct_array(void *ptr,ConstructorDestructor ctor,ConstructorDestructor dtor,size_t size,size_t n)
  277. {
  278.     __partial_array_destructor pad(ptr,size,n,dtor);
  279.     char    *p;
  280.  
  281.     for(pad.i=0,p=(char *)ptr; pad.i<n; pad.i++,p+=size) CTORCALL_COMPLETE(ctor,p);
  282. }
  283.  
  284. #endif
  285.  
  286. /************************************************************************/
  287. /*    Purpose..:     Destroy an array of objects                                */
  288. /*    Input....:    pointer to array memory                                    */
  289. /*    Input....:    pointer to destructor function                            */
  290. /*    Input....:    size of one object                                        */
  291. /*    Input....:    number of objects                                        */
  292. /*    Return...:    ---                                                        */
  293. /************************************************************************/
  294. extern void __destroy_arr(void *block,ConstructorDestructor dtor,size_t size,size_t n)
  295. {
  296.     char    *p;
  297.  
  298.     for(p=(char *)block+size*n; n>0; n--)
  299.     {
  300.         p-=size;
  301.         DTORCALL_COMPLETE(dtor,p);
  302.     }
  303. }
  304.  
  305. /************************************************************************/
  306. /*    Purpose..:     Delete an array of objects                                */
  307. /*    Input....:    pointer to first object    (can be 0L)                        */
  308. /*    Input....:    pointer to destructor function                            */
  309. /*    Return...:    ---                                                        */
  310. /************************************************************************/
  311. extern void __destroy_new_array(void *block,ConstructorDestructor dtor)
  312. {
  313.     if(block)
  314.     {
  315.         if(dtor)
  316.         {
  317.             size_t    i,objects,objectsize;
  318.             char    *p;
  319.  
  320.             objectsize=*(size_t *)((char *)block-2*sizeof(size_t));
  321.             objects=*(size_t *)((char *)block-sizeof(size_t));
  322.             p=(char *)block+objectsize*objects;
  323.             for(i=0; i<objects; i++)
  324.             {
  325.                 p-=objectsize;
  326.                 DTORCALL_COMPLETE(dtor,p);
  327.             }
  328.         }
  329.         ::delete ((char *)block-2*sizeof(size_t));
  330.     }
  331. }
  332.